package com.xjve.framework.hibernate.jpa;

import org.springframework.stereotype.Component;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.*;
import java.util.regex.Pattern;

/**
 * HQL生成器，根据Search对象自动生成HQL查询语句和元数据
 */
@Component
public class HqlGenerator {

    @PersistenceContext
    private EntityManager entityManager;

    // 操作符处理器映射
    private final List<OperatorHandler> operatorHandlers = new ArrayList<>();

    public HqlGenerator() {
        initOperatorHandlers();
    }

    /**
     * 初始化操作符处理器
     */
    private void initOperatorHandlers() {
        // 模糊查询 - 全匹配
        addHandler(createHandler("_fuzzy", "like", value -> "%" + value.toString() + "%"));

        // 模糊查询 - 左匹配
        addHandler(createHandler("_like", "like", value -> value.toString() + "%"));

        // 模糊查询 - 右匹配
        addHandler(createHandler("like_", "like", value -> "%" + value.toString()));

        // 非模糊查询
        addHandler(createHandler("_noFuzzy", "not like", value -> "%" + value.toString() + "%"));

        // 小于
        addHandler(createHandler("_lt", "<", null));

        // 小于等于
        addHandler(createHandler("_le", "<=", null));

        // 大于
        addHandler(createHandler("_gt", ">", null));

        // 大于等于
        addHandler(createHandler("_ge", ">=", null));

        // 不等于
        addHandler(createHandler("_not", "!=", null));

        // 等于（默认）
        addHandler(createHandler("_eq", "=", null));

        // IN查询
        addHandler(createHandler("_in", "in", null));

        // NOT IN查询
        addHandler(createHandler("_notIn", "not in", null));
    }

    /**
     * 创建操作符处理器
     */
    private OperatorHandler createHandler(String suffix, String operator, ValueProcessor processor) {
        return new OperatorHandler(suffix, operator, processor);
    }

    /**
     * 添加操作符处理器
     */
    private void addHandler(OperatorHandler handler) {
        operatorHandlers.add(handler);
    }

    /**
     * 生成查询上下文
     */
    public <T> QueryContext generateQueryContext(BaseSearch<T> search, boolean countQuery) {
        Class<T> entityClass = search.getEntityClass();
        String entityName = getEntityName(entityClass);

        StringBuilder hql = new StringBuilder();
        List<SearchFieldMetadata> fieldMetadataList = new ArrayList<>();

        if (countQuery) {
            hql.append("SELECT COUNT(*) FROM ").append(entityName).append(" WHERE 1=1");
        } else {
            hql.append("FROM ").append(entityName).append(" WHERE 1=1");
        }

        // 处理查询条件
        processSearchFields(search, hql, fieldMetadataList);

        // 处理排序
        if (!countQuery) {
            processOrderBy(search, hql);
        }

        return new QueryContext(hql.toString(), fieldMetadataList);
    }

    /**
     * 获取实体类的名称
     */
    private <T> String getEntityName(Class<T> entityClass) {
        javax.persistence.Entity entityAnnotation = entityClass.getAnnotation(javax.persistence.Entity.class);
        if (entityAnnotation != null && !entityAnnotation.name().isEmpty()) {
            return entityAnnotation.name();
        }
        return entityClass.getSimpleName();
    }

    /**
     * 处理查询条件并生成元数据
     */
    private void processSearchFields(BaseSearch<?> search, StringBuilder hql,
                                   List<SearchFieldMetadata> metadataList) {
        List<Field> fields = getAllFields(search.getClass());

        for (Field field : fields) {
            if (field.isAnnotationPresent(SearchIgnore.class)) {
                continue;
            }

            try {
                field.setAccessible(true);
                Object value = field.get(search);

                if (value == null) {
                    continue;
                }

                String fieldName = getSearchFieldName(field);
                OperatorHandler handler = determineOperatorHandler(field.getName());
                String actualFieldName = getActualFieldName(fieldName, handler.getSuffix());
                String operator = handler.getOperator();
                Object processedValue = handler.getProcessor() != null ?
                                      handler.getProcessor().process(value) : value;
                String paramName = sanitizeParamName(actualFieldName);

                // 创建注解映射
                Map<Class<? extends Annotation>, Annotation> annotations = new HashMap<>();
                Annotation[] fieldAnnotations = field.getAnnotations();
                for (Annotation annotation : fieldAnnotations) {
                    annotations.put(annotation.annotationType(), annotation);
                }

                // 创建元数据对象
                SearchFieldMetadata metadata = new SearchFieldMetadata(
                    field, fieldName, value, annotations, actualFieldName,
                    operator, processedValue, paramName
                );

                metadataList.add(metadata);

                // 生成查询条件
                generateCondition(hql, actualFieldName, handler, value);

            } catch (IllegalAccessException e) {
                throw new RuntimeException("Failed to process search field", e);
            }
        }
    }

    /**
     * 获取所有字段（包括父类字段）
     */
    private List<Field> getAllFields(Class<?> clazz) {
        List<Field> fields = new ArrayList<>();
        while (clazz != null && clazz != Object.class) {
            Field[] declaredFields = clazz.getDeclaredFields();
            Collections.addAll(fields, declaredFields);
            clazz = clazz.getSuperclass();
        }
        return fields;
    }

    /**
     * 获取查询字段名
     */
    private String getSearchFieldName(Field field) {
        if (field.isAnnotationPresent(SearchField.class)) {
            return field.getAnnotation(SearchField.class).value();
        }
        return field.getName();
    }

    /**
     * 确定操作符处理器
     */
    private OperatorHandler determineOperatorHandler(String fieldName) {
        for (OperatorHandler handler : operatorHandlers) {
            if (handler.matches(fieldName)) {
                return handler;
            }
        }
        // 默认等于操作符
        return operatorHandlers.stream()
                .filter(h -> "_eq".equals(h.getSuffix()))
                .findFirst()
                .orElseThrow(() -> new IllegalStateException("Default operator handler not found"));
    }

    /**
     * 获取实际的字段名（去除操作符后缀）
     */
    private String getActualFieldName(String fieldName, String suffix) {
        if (suffix != null && !suffix.isEmpty() && fieldName.endsWith(suffix)) {
            return fieldName.substring(0, fieldName.length() - suffix.length());
        }
        return fieldName;
    }

    /**
     * 生成查询条件
     */
    private void generateCondition(StringBuilder hql, String fieldName, OperatorHandler handler, Object value) {
        hql.append(" AND ").append(fieldName).append(" ").append(handler.getOperator()).append(" :")
                .append(sanitizeParamName(fieldName));
    }

    /**
     * 处理排序
     */
    private void processOrderBy(BaseSearch<?> search, StringBuilder hql) {
        List<OrderByInfo> orderByInfos = new ArrayList<>();
        List<Field> fields = getAllFields(search.getClass());

        for (Field field : fields) {
            if (field.isAnnotationPresent(OrderBy.class)) {
                OrderBy orderBy = field.getAnnotation(OrderBy.class);
                String fieldName = orderBy.value();
                String direction = orderBy.direction().name();
                int priority = orderBy.priority();

                orderByInfos.add(new OrderByInfo(fieldName, direction, priority));
            }
        }

        // 按优先级排序
        orderByInfos.sort((o1, o2) -> {
            if (o1.getPriority() != o2.getPriority()) {
                return Integer.compare(o1.getPriority(), o2.getPriority());
            }
            return o1.getFieldName().compareTo(o2.getFieldName());
        });

        if (!orderByInfos.isEmpty()) {
            hql.append(" ORDER BY ");
            for (int i = 0; i < orderByInfos.size(); i++) {
                OrderByInfo info = orderByInfos.get(i);
                hql.append(info.getFieldName()).append(" ").append(info.getDirection());
                if (i < orderByInfos.size() - 1) {
                    hql.append(", ");
                }
            }
        }
    }

    /**
     * 清理参数名，将非法字符替换为下划线
     */
    private String sanitizeParamName(String fieldName) {
        return fieldName.replaceAll("[^a-zA-Z0-9_]", "_");
    }

    /**
     * 排序信息封装
     */
    private static class OrderByInfo {
        private final String fieldName;
        private final String direction;
        private final int priority;

        public OrderByInfo(String fieldName, String direction, int priority) {
            this.fieldName = fieldName;
            this.direction = direction;
            this.priority = priority;
        }

        public String getFieldName() { return fieldName; }
        public String getDirection() { return direction; }
        public int getPriority() { return priority; }
    }

    /**
     * 操作符处理器
     */
    private static class OperatorHandler {
        private final String suffix;
        private final String operator;
        private final ValueProcessor processor;

        public OperatorHandler(String suffix, String operator, ValueProcessor processor) {
            this.suffix = suffix;
            this.operator = operator;
            this.processor = processor;
        }

        public boolean matches(String fieldName) {
            if (suffix == null || suffix.isEmpty()) {
                return false;
            }
            return fieldName.endsWith(suffix);
        }

        public String getSuffix() { return suffix; }
        public String getOperator() { return operator; }
        public ValueProcessor getProcessor() { return processor; }
    }

    /**
     * 值处理器接口
     */
    @FunctionalInterface
    private interface ValueProcessor {
        Object process(Object value);
    }
}
